package com.mofang.ticketing.common.redis.distributedLock;


import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * redisson 分布式锁实现
 *
 * @author LGC
 */
@Slf4j
@AllArgsConstructor
public class RedissonLocker implements DistributedLocker {

    public static final String LOCKER_PREFIX = "redisson:lock:";

    private final RedissonClient redissonClient;

    @Override
    public <T> T lock(String resourceName, AcquireLockWorker<T> worker) throws Throwable {
        return lock(resourceName, worker, TIME_OUT, TimeUnit.SECONDS);
    }

    @Override
    public <T> T lock(String resourceName, AcquireLockWorker<T> worker, long timeOut, TimeUnit timeUnit) throws Throwable {
        return lock(resourceName, worker, 3, timeOut, timeUnit);
    }

    @Override
    public <T> T lock(String resourceName, AcquireLockWorker<T> worker, long ctyTime, long timeOut, TimeUnit timeUnit) throws Throwable {
        RLock lock = redissonClient.getLock(LOCKER_PREFIX + resourceName);
        boolean success = lock.tryLock(ctyTime, timeOut, timeUnit);
        if (success) {
            log.info(resourceName + "，获得锁");
            try {
                return worker.invokeAfterLockAcquire();
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                    log.info(resourceName + "，释放锁");
                }
            }
        }
        throw new UnableToAcquireLockException();
    }
}